﻿using Aliyun.Acs.afs.Model.V20180112;
using Aliyun.Acs.Core;
using Aliyun.Acs.Core.Profile;
using Common.Cache;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.Configuration;
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace Common.Aliyun
{
    /// <summary>
    /// 阿里云行为验证码验证对象
    /// </summary>
    public class AliyunCaptchaVerification : IBehaviorCaptcha
    {
        /// <summary>
        /// afs-id 配置名称
        /// </summary>
        public const string NAME_OF_AFS_ID = "aliyun-afs-id";
        /// <summary>
        /// 行为验证码规则JSON
        /// </summary>
        public const string SCORE_JSON = "{\"200\":\"PASS\",\"400\":\"NC\",\"600\":\"SC\",\"700\":\"LC\",\"800\":\"BLOCK\"}";
        private readonly IConfiguration Configuration;
        private readonly IRedisCache redis;
        /// <summary>
        /// 阿里云行为验证码验证对象
        /// </summary>
        /// <param name="configuration"></param>
        /// <param name="redis"></param>
        public AliyunCaptchaVerification(IConfiguration configuration, IRedisCache redis)
        {
            this.Configuration = configuration;
            this.redis = redis;
        }
        /// <summary>
        /// 无痕验证
        /// </summary>
        /// <param name="captcha"></param>
        /// <returns></returns>
        public ICaptchaComponentResult Init(string captcha)
        {
            IClientProfile profile = DefaultProfile.GetProfile("cn-hangzhou", Configuration[Constants.NAME_OF_ACCESS_ID], Configuration[Constants.NAME_OF_ACCESS_SECRET]);
            profile.AddEndpoint("cn-hangzhou", "cn-hangzhou", "afs", Configuration[Constants.NAME_OF_AFS_SERVER]);//"afs.aliyuncs.com"

            IAcsClient client = new DefaultAcsClient(profile);

            AnalyzeNvcRequest request = new AnalyzeNvcRequest();
            request.Data = captcha;//必填参数，来自前端getNVCVal函数的值
            request.ScoreJsonStr = SCORE_JSON;// 必填参数，处罚设置

            AnalyzeNvcResponse response = client.GetAcsResponse(request);
            redis.Add($"aliyun-captcha:{response.RequestId}", response.BizCode, TimeSpan.FromMinutes(10));
            return new AliyunCaptchaResult { RequestId = response.RequestId, BizCode = response.BizCode };

        }
        /// <summary>
        /// 校验行为验证码
        /// </summary>
        /// <param name="data"></param>
        /// <param name="captchaId"></param>
        /// <returns></returns>
        public FuncResult Verify(string captchaId, string data)
        {
            string key = $"aliyun-captcha:{captchaId}";
            var score = redis.GetString(key);
            if (string.IsNullOrEmpty(score))
            {
                return FuncResult.Fail("人机验证码已过期");
            }
            if (Environment.GetEnvironmentVariable("ASPNETCORE_ENVIRONMENT") != "Development")
            {
                redis.Delete(key);
            }
            if (score == "100" || score == "200")
            {
                return FuncResult.Success();
            }
            //var arg = JsonConvert.DeserializeObject<AliyunCaptchaSigRequest>(data);
            IClientProfile profile = DefaultProfile.GetProfile("cn-hangzhou", Configuration[Constants.NAME_OF_ACCESS_ID], Configuration[Constants.NAME_OF_ACCESS_SECRET]);
            profile.AddEndpoint("cn-hangzhou", "cn-hangzhou", "afs", Configuration[Constants.NAME_OF_AFS_SERVER]);

            IAcsClient client = new DefaultAcsClient(profile);

            AnalyzeNvcRequest request = new AnalyzeNvcRequest();
            request.Data = data;
            request.ScoreJsonStr = SCORE_JSON;

            //response的code枚举：100验签通过，900验签失败                                                                                                                      
            AnalyzeNvcResponse response = client.GetAcsResponse(request);
            return response.BizCode == "100" ? FuncResult.Success() : FuncResult.Fail("请先完成人机验证");
        }
        private static string GetRemoteIP(HttpContext context)
        {
            string xforwarded = context.Request.Headers["x-forwarded-for"];
            if (string.IsNullOrEmpty(xforwarded))
            {
                return context.Connection.RemoteIpAddress.ToString();
            }
            string clientAddr = xforwarded.Split(',').FirstOrDefault();
            if (clientAddr.Contains(":"))
            {
                clientAddr = clientAddr.Substring(0, clientAddr.IndexOf(":"));
            }
            return clientAddr;
        }
    }
}
